#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "linux/ioctl.h"
#include "drv_rf24l01.h"
#include "utility.h"
#include "spi.h"
#include "utility.h"


const char *g_ErrorString = "RF24L01 is not find !...";

/**
 *  CE=0 时，芯片将由Idle-TX、TX 或 RX 模式返回到 Standby 模式
 * 
 */
void RF24L01_SET_CE_LOW( ){
    executionScriptCommand("echo 0 > /sys/class/gpio/gpio12/value");
    usleep(1000);
}

/**
 * 当引脚CE=1 时，芯片将由 Standby 模式进入到 Idle-TX 或 RX 模式
 * 
 */
void RF24L01_SET_CE_HIGH( ){
    executionScriptCommand("echo 1 > /sys/class/gpio/gpio12/value");
    usleep(1000);
}


int RF24L01_GET_IRQ_STATUS( ){
    return 0;
}

/**
  * @brief :SPI收发一个字节
  * @param :
  *			@TxByte: 发送的数据字节
  * @note  :非堵塞式，一旦等待超时，函数会自动退出
  * @retval:接收到的字节
  */
uint8_t drv_spi_read_write_byte( uint8_t TxByte )
{
    int ret = 0;
    const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
	tx[0] = TxByte;
	ret = SPI_Transfer(tx, rx, 1, 1);
    if (ret > 1)
    {
        ;
    }
	return rx[0];
}

/**
  * @brief :NRF24L01读寄存器
  * @param :
           @Addr:寄存器地址
  * @note  :地址在设备中有效
  * @retval:读取的数据
  */
uint8_t NRF24L01_Read_Reg( uint8_t RegAddr, int outputLog)
{
    int ret;
    uint8_t btmp;
	const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
	tx[0] = NRF_READ_REG | RegAddr;
	ret = SPI_Transfer(tx, rx, 2, outputLog);
    return rx[1];
}

/**
  * @brief :NRF24L01读指定长度的数据
  * @param :
  *			@reg:地址
  *			@pBuf:数据存放地址
  *			@len:数据长度
  * @note  :数据长度不超过255，地址在设备中有效
  * @retval:读取状态
  */
void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len, int outputLog)
{
    int ret;
    uint8_t btmp;
	const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
	tx[0] = NRF_READ_REG | RegAddr;
	ret = SPI_Transfer(tx, pBuf, len + 1, outputLog);


	
    // drv_spi_read_write_byte( NRF_READ_REG | RegAddr );	//读命令 地址
    // for( btmp = 0; btmp < len; btmp ++ )
    // {
    //     *( pBuf + btmp ) = drv_spi_read_write_byte( 0xFF );	//读数据
    // }
}

/**
  * @brief :NRF24L01写寄存器
  * @param :无
  * @note  :地址在设备中有效
  * @retval:读写状态
  */
void NRF24L01_Write_Reg(uint8_t RegAddr, uint8_t Value, int outputLog)
{
    int ret;
    const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
	tx[0] = NRF_WRITE_REG | RegAddr;
    tx[1] = Value;
	ret = SPI_Transfer(tx, rx, 2, outputLog);

	
    // drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );	//写命令 地址
    // drv_spi_read_write_byte( Value );			//写数据
	
}

/**
  * @brief :NRF24L01写指定长度的数据
  * @param :
  *			@reg:地址
  *			@pBuf:写入的数据地址
  *			@len:数据长度
  * @note  :数据长度不超过255，地址在设备中有效
  * @retval:写状态
  */
void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
    int ret;
    uint8_t i;
	const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
	tx[0] = NRF_WRITE_REG | RegAddr;
    for( i = 0; i < len; i ++ )
    {
        tx[i + 1] = *( pBuf + i );		//写数据
    }
	ret = SPI_Transfer(tx, rx, 6, 1);

	
    // drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );	//写命令 地址
    // for( i = 0; i < len; i ++ )
    // {
    //     drv_spi_read_write_byte( *( pBuf + i ) );		//写数据
    // }
	
}

/**
  * @brief :清空TX缓冲区
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Flush_Tx_Fifo ( void )
{
	
    drv_spi_read_write_byte( FLUSH_TX );	//清TX FIFO命令
	
}

/**
  * @brief :清空RX缓冲区
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Flush_Rx_Fifo( void )
{
	
    drv_spi_read_write_byte( FLUSH_RX );	//清RX FIFO命令
	
}

/**
  * @brief :重新使用上一包数据
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Reuse_Tx_Payload( void )
{
	
    drv_spi_read_write_byte( REUSE_TX_PL );		//重新使用上一包命令
	
}

/**
  * @brief :NRF24L01空操作
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Nop( void )
{
	
    drv_spi_read_write_byte( NOP );		//空操作命令
	
}

/**
  * @brief :NRF24L01读状态寄存器
  * @param :无
  * @note  :无
  * @retval:RF24L01状态
  */
uint8_t NRF24L01_Read_Status_Register( void )
{
    int ret;
    uint8_t Status;
	const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];

	
    //Status = drv_spi_read_write_byte( NRF_READ_REG + STATUS );	//读状态寄存器
    tx[0] = NRF_READ_REG + STATUS;
    ret = SPI_Transfer(tx, rx, 2, 1);
	
	
    return rx[1];
}

/**
  * @brief :NRF24L01清中断
  * @param :
           @IRQ_Source:中断源
  * @note  :无
  * @retval:清除后状态寄存器的值
  */
uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source )
{
    int ret;
    uint8_t btmp = 0;
    const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
	
    IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT );	//中断标志处理
    btmp = NRF24L01_Read_Status_Register( );			//读状态寄存器
			
    // drv_spi_read_write_byte( NRF_WRITE_REG + STATUS );	//写状态寄存器命令
    // drv_spi_read_write_byte( IRQ_Source | btmp );		//清相应中断标志
	
    tx[0] = NRF_WRITE_REG + STATUS;
    tx[1] = IRQ_Source | btmp;
    ret = SPI_Transfer(tx, rx, 2, 1);

    return ( NRF24L01_Read_Status_Register( ));			//返回状态寄存器状态
}

/**
  * @brief :读RF24L01中断状态
  * @param :无
  * @note  :无
  * @retval:中断状态
  */
uint8_t RF24L01_Read_IRQ_Status( void )
{
    return ( NRF24L01_Read_Status_Register( ) & (( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT )));	//返回中断状态
}
 
 /**
  * @brief :读FIFO中数据宽度
  * @param :无
  * @note  :无
  * @retval:数据宽度
  */
uint8_t NRF24L01_Read_Top_Fifo_Width( void )
{
    uint8_t btmp;
	
	
    drv_spi_read_write_byte( R_RX_PL_WID );	//读FIFO中数据宽度命令
    btmp = drv_spi_read_write_byte( 0xFF );	//读数据
	
	
    return btmp;
}

 /**
  * @brief :读接收到的数据
  * @param :无
  * @note  :无
  * @retval:
           @pRxBuf:数据存放地址首地址
  */
uint8_t NRF24L01_Read_Rx_Payload( uint8_t *pRxBuf )
{
    uint8_t Width, PipeNum;
	
    PipeNum = ( NRF24L01_Read_Reg(STATUS, 1) >> 1 ) & 0x07;	//读接收状态
    Width = NRF24L01_Read_Top_Fifo_Width( );		//读接收数据个数

    drv_spi_read_write_byte( RD_RX_PLOAD );			//读有效数据命令
	
    for( PipeNum = 0; PipeNum < Width; PipeNum ++ )
    {
        *( pRxBuf + PipeNum ) = drv_spi_read_write_byte( 0xFF );		//读数据
    }
    NRF24L01_Flush_Rx_Fifo( );	//清空RX FIFO
	
    return Width;
}

 /**
  * @brief :发送数据（带应答）
  * @param :
  *			@pTxBuf:发送数据地址
  *			@len:长度
  * @note  :一次不超过32个字节
  * @retval:无
  */
void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len )
{
    uint8_t btmp;
    uint8_t length = ( len > 32 ) ? 32 : len;		//数据长达大约32 则只发送32个

    NRF24L01_Flush_Tx_Fifo( );		//清TX FIFO
	
    drv_spi_read_write_byte( WR_TX_PLOAD );	//发送命令
	
    for( btmp = 0; btmp < length; btmp ++ )
    {
        drv_spi_read_write_byte( *( pTxBuf + btmp ) );	//发送数据
    }
}

 /**
  * @brief :发送数据（不带应答）
  * @param :
  *			@pTxBuf:发送数据地址
  *			@len:长度
  * @note  :一次不超过32个字节
  * @retval:无
  */
void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len )
{
    if( len > 32 || len == 0 )
    {
        return ;		//数据长度大于32 或者等于0 不执行
    }
	
    drv_spi_read_write_byte( WR_TX_PLOAD_NACK );	//发送命令
    while( len-- )
    {
        drv_spi_read_write_byte( *pTxBuf );			//发送数据
		pTxBuf++;
    }
}

 /**
  * @brief :在接收模式下向TX FIFO写数据(带ACK)
  * @param :
  *			@pData:数据地址
  *			@len:长度
  * @note  :一次不超过32个字节
  * @retval:无
  */
void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len )
{
    uint8_t btmp;
	
	len = ( len > 32 ) ? 32 : len;		//数据长度大于32个则只写32个字节

    drv_spi_read_write_byte( W_ACK_PLOAD );		//命令
    for( btmp = 0; btmp < len; btmp ++ )
    {
        drv_spi_read_write_byte( *( pData + btmp ) );	//写数据
    }
}

 /**
  * @brief :设置发送地址
  * @param :
  *			@pAddr:地址存放地址
  *			@len:长度
  * @note  :无
  * @retval:无
  */
void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len )
{
	len = ( len > 5 ) ? 5 : len;					//地址不能大于5个字节
    NRF24L01_Write_Buf( TX_ADDR, pAddr, 6 );	//写地址
}

 /**
  * @brief :设置接收通道地址
  * @param :
  *			@PipeNum:通道
  *			@pAddr:地址存肥着地址
  *			@Len:长度
  * @note  :通道不大于5 地址长度不大于5个字节
  * @retval:无
  */
void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len )
{
    Len = ( Len > 5 ) ? 5 : Len;
    PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum;		//通道不大于5 地址长度不大于5个字节

    NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, 6 );	//写入地址
}

 /**
  * @brief :设置通信速度
  * @param :
  *			@Speed:速度
  * @note  :无
  * @retval:无
  */
void NRF24L01_Set_Speed( nRf24l01SpeedType Speed )
{
	uint8_t btmp = 0;
	
	btmp = NRF24L01_Read_Reg(RF_SETUP, 1);
	btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
	
	if( Speed == SPEED_250K )		//250K
	{
		btmp |= ( 1<<5 );
	}
	else if( Speed == SPEED_1M )   //1M
	{
   		btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
	}
	else if( Speed == SPEED_2M )   //2M
	{
		btmp |= ( 1<<3 );
	}

	NRF24L01_Write_Reg(RF_SETUP, btmp, 1);
}

 /**
  * @brief :设置功率
  * @param :
  *			@Speed:速度
  * @note  :无
  * @retval:无
  */
void NRF24L01_Set_Power( nRf24l01PowerType Power )
{
    uint8_t btmp;
	
	btmp = NRF24L01_Read_Reg(RF_SETUP, 1) & ~0x07;
    switch( Power )
    {
        case POWER_F18DBM:
            btmp |= PWR_18DB;
            break;
        case POWER_F12DBM:
            btmp |= PWR_12DB;
            break;
        case POWER_F6DBM:
            btmp |= PWR_6DB;
            break;
        case POWER_0DBM:
            btmp |= PWR_0DB;
            break;
        default:
            break;
    }
    NRF24L01_Write_Reg( RF_SETUP, btmp, 1);
}

 /**
  * @brief :设置频率
  * @param :
  *			@FreqPoint:频率设置参数
  * @note  :值不大于127
  * @retval:无
  */
void RF24LL01_Write_Hopping_Point( uint8_t FreqPoint )
{
    NRF24L01_Write_Reg(  RF_CH, FreqPoint & 0x7F, 1);
}

/**
  * @brief :NRF24L01检测
  * @param :无
  * @note  :无
  * @retval:无
  */ 
void NRF24L01_check( void )
{
	uint8_t i;
	uint8_t buf[5]={0XA5, 0XA5, 0XA5, 0XA5, 0XA5};
	uint8_t read_buf[ 5 ] = { 0 };

	uint8_t sendBuff[6] = {NRF_WRITE_REG | TX_ADDR, 0XA5, 0XA5, 0XA5, 0XA5, 0XA5};
    uint8_t rxBuff[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    uint8_t sendBuff_1[6] = {NRF_READ_REG | TX_ADDR, 0x00, 0x00, };
    uint8_t rxBuff_1[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    printf("NRF24L01_check(), enter\n");

    printf("NRF24L01_check(), start write\n");
    SPI_Transfer(sendBuff, rxBuff, 6, 1);
    sleep(1);
    printf("NRF24L01_check(), start read\n");
    SPI_Transfer(sendBuff_1, rxBuff_1, 6, 1);
    for( i = 1; i < 5; i++ )
    {
        if( buf[ i ] != rxBuff_1[ i ] )
        {
            printf("NRF24L01_check(), fail, exit programme\n");
            exit(0);
        }
    }
    printf("NRF24L01_check(), test success\n");
}

 /**
  * @brief :设置模式
  * @param :
  *			@Mode:模式发送模式或接收模式
  * @note  :无
  * @retval:无
  */
void RF24L01_Set_Mode( nRf24l01ModeType Mode )
{
    uint8_t controlreg = 0;
	controlreg = NRF24L01_Read_Reg(CONFIG, 1);
	printf("RF24L01_Set_Mode(), controlreg=0x%02x\n", controlreg);
    if( Mode == MODE_TX )
	{
		controlreg &= ~( 1<< PRIM_RX );
	}
    else 
	{
		if( Mode == MODE_RX )  
		{ 
			controlreg |= ( 1<< PRIM_RX );
            controlreg &= ~( 1 << MASK_RX_DR );//开接收中断
            controlreg &= ~( 1 << MASK_TX_DS );//开发送中断

            printf("RF24L01_Set_Mode(), end, controlreg=0x%02x\n", controlreg);
		}
	}

    NRF24L01_Write_Reg( CONFIG, controlreg, 1);
}

/**
  * @brief :NRF24L01发送一次数据
  * @param :
  *			@txbuf:待发送数据首地址
  *			@Length:发送数据长度
  * @note  :无
  * @retval:
  *			MAX_TX：达到最大重发次数
  *			TX_OK：发送完成
  *			0xFF:其他原因
  */ 
uint8_t NRF24L01_TxPacket( uint8_t *txbuf, uint8_t Length )
{
	uint8_t l_Status = 0;
	uint16_t l_MsTimes = 0;
	
	drv_spi_read_write_byte( FLUSH_TX );
	
	RF24L01_SET_CE_LOW( );
	NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length );	//写数据到TX BUF 32字节  TX_PLOAD_WIDTH
	RF24L01_SET_CE_HIGH( );			//启动发送
	while( 0 != RF24L01_GET_IRQ_STATUS( ))
	{
		usleep(1000);
		if( 500 == l_MsTimes++ )						//500ms还没有发送成功，重新初始化设备
		{
			RF24L01_Init( );
			RF24L01_Set_Mode( MODE_TX );
			break;
		}
	}
	l_Status = NRF24L01_Read_Reg(STATUS, 1);						//读状态寄存器
	NRF24L01_Write_Reg( STATUS, l_Status, 1);						//清除TX_DS或MAX_RT中断标志
	
	if( l_Status & MAX_TX )	//达到最大重发次数
	{
		NRF24L01_Write_Reg( FLUSH_TX,0xff, 1);	//清除TX FIFO寄存器
		return MAX_TX; 
	}
	if( l_Status & TX_OK )	//发送完成
	{
		return TX_OK;
	}
	
	return 0xFF;	//其他原因发送失败
}

/**
  * @brief :NRF24L01接收数据
  * @param :
  *			@rxbuf:接收数据存放地址
  * @note  :无
  * @retval:接收到的数据个数
  */ 
uint8_t NRF24L01_RxPacket()
{
	uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
    uint8_t flagInitRF24L01 = 0;
	uint8_t rxbuf[ 32 ] = {0x00}; 
	int fd;
	int ret = 0;
	char *filename;
	unsigned char data = 0;
	int i = 0;

    RF24L01_SET_CE_HIGH( );
	drv_spi_read_write_byte( FLUSH_RX );
	
	while(flagInitRF24L01)
	{
		usleep(1000);
		if( 30 == l_100MsTimes++ )		//3s没接收过数据，重新初始化模块
		{
			RF24L01_Init( );
			RF24L01_Set_Mode( MODE_RX );
			break;
		}
	}
	
	filename = "/dev/gpio90IrqDev";
	fd = open(filename, O_RDWR);
	if (fd < 0) {
		LV_LOG_USER("Can't open file %s\r\n", filename);
		return -1;
	}
	LV_LOG_USER("open file %s success.\r\n", filename);
	while (1) {
		usleep(10000);
		ret = read(fd, &data, sizeof(data));
		if (ret < 0) {
			/* 数据读取错误或者无效 */
			continue;
		}
		/* 数据读取正确 */
		if (data){
			i++;
			/* 读取到数据 */
			printf("i=%d, iqr value = %02X\r\n", i, data);
            NRF24L01_read_receive_data();
		}		
	}
	close(fd);
	return 0;				//没有收到数据	
}

void NRF24L01_read_receive_data(){
    uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
    uint8_t flagInitRF24L01 = 0;
	uint8_t rxbuf[ 32 ] = {0x00}; 

    l_Status = NRF24L01_Read_Reg(STATUS, 0);		//读状态寄存器
    NRF24L01_Write_Reg( STATUS,l_Status, 0);		//清中断标志
    if( l_Status & RX_OK)	//接收到数据
    {
        l_RxLength = NRF24L01_Read_Reg(R_RX_PL_WID, 0);		//读取接收到的数据个数
        memset(rxbuf, 0x00, 32);
        NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength, 0);	//接收到数据 
        NRF24L01_Write_Reg( FLUSH_RX,0xff, 0);				//清除RX FIFO
        printf("NRF24L01_RxPacket(), success rxbuf=%s\n", (rxbuf + 1));
    }
}

 /**
  * @brief :RF24L01引脚初始化
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Gpio_Init( void )
{	
	RF24L01_SET_CE_LOW( );		//使能设备
	//RF24L01_SET_CS_HIGH( );		//取消SPI片选
}

 /**
  * @brief :RF24L01模块初始化
  * @param :无
  * @note  :无
  * @retval:无
  */
void RF24L01_Init( void )
{
    uint8_t addr[5] = {INIT_ADDR};

    RF24L01_SET_CE_LOW( );
    NRF24L01_Clear_IRQ_Flag( IRQ_ALL );
#if DYNAMIC_PACKET == 1

    printf("write DYNPD\n");
    NRF24L01_Write_Reg( DYNPD, ( 1 << 0 ), 1); 	//使能通道1动态数据长度
    NRF24L01_Write_Reg( FEATRUE, 0x07, 1);
    printf("read DYNPD\n");
    NRF24L01_Read_Reg(DYNPD, 1);
    NRF24L01_Read_Reg(FEATRUE, 1);
	
#elif DYNAMIC_PACKET == 0
    
    L01_WriteSingleReg( L01REG_RX_PW_P0, FIXED_PACKET_LEN );	//固定数据长度
	
#endif	//DYNAMIC_PACKET

    NRF24L01_Write_Reg( CONFIG, /*( 1<<MASK_RX_DR ) |*/		//接收中断
                                      ( 1 << EN_CRC ) |     //使能CRC 1个字节
                                      ( 1 << PWR_UP ), 1);    //开启设备
    NRF24L01_Write_Reg( EN_AA, ( 1 << ENAA_P0 ), 1);   		//通道0自动应答
    NRF24L01_Write_Reg( EN_RXADDR, ( 1 << ERX_P0 ), 1);		//通道0接收
    NRF24L01_Write_Reg( SETUP_AW, AW_5BYTES, 1);     			//地址宽度 5个字节
    NRF24L01_Write_Reg( SETUP_RETR, ARD_4000US |
                        ( REPEAT_CNT & 0x0F ), 1);         	//重复等待时间 250us
    NRF24L01_Write_Reg( RF_CH, 60, 1);             			//初始化通道
    NRF24L01_Write_Reg( RF_SETUP, 0x26, 1);

    printf("write Tx addr\n");
    NRF24L01_Set_TxAddr( &addr[0], 5 );                      //设置TX地址
    printf("write Rx addr\n");
    NRF24L01_Set_RxAddr( 0, &addr[0], 5 );                   //设置RX地址
}
